package com.relytosoft.mizar.media.display.services.service.impl;


import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.relytosoft.dubhe.common.core.object.ResponseResult;
import com.relytosoft.dubhe.common.redis.utils.RedisUtil;
import com.relytosoft.mizar.media.camera.api.entity.CameraPlatform;
import com.relytosoft.mizar.media.camera.api.feign.CameraFeignInService;
import com.relytosoft.mizar.media.common.constant.MediaMqConstants;
import com.relytosoft.mizar.media.common.emqx.client.MqttOp;
import com.relytosoft.mizar.media.display.api.entity.CruiseControl;
import com.relytosoft.mizar.media.display.api.entity.CruiseTrack;
import com.relytosoft.mizar.media.display.api.enums.CruiseCommand;
import com.relytosoft.mizar.media.display.api.pojo.dto.CruiseTrackDto;
import com.relytosoft.mizar.media.display.services.mapper.CruiseTrackMapper;
import com.relytosoft.mizar.media.display.services.service.CruiseTrackService;
import com.relytosoft.mizar.media.display.services.utils.ResponseUtils;
import com.relytosoft.mizar.media.external.api.display.request.CruiseDto;
import com.relytosoft.mizar.media.external.api.display.service.CruisePathService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.relytosoft.mizar.media.display.api.enums.CruiseCommand.CRUISE_START;
import static com.relytosoft.mizar.media.display.services.constants.OperationConstant.*;

/**
 * 海康巡航轨迹实现类
 *
 * @author hj
 * @version 1.0
 * @date 2022/4/7 10:50
 * @ClassName HkCruiseTrackServiceImpl
 */
@Service
public class CruiseTrackServiceImpl extends ServiceImpl<CruiseTrackMapper, CruiseTrack> implements CruiseTrackService{
    public static final int MAX_SIZE = 8;
    public static final String PTZ_CRUISE = "PtzCruise:";
    @Resource
    private CruisePathService cruisePathService;

    @Resource
    private CameraFeignInService cameraFeignInService;



    /**
     * 查询当前索引下有无数据
     * @author jgg
     * @date 2022/4/11 11:23
     * @param track
     * @return com.relytosoft.mizar.media.display.api.entity.CruiseTrack
     */
    private CruiseTrack isSave(CruiseTrack track){
        LambdaQueryWrapper<CruiseTrack> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(CruiseTrack::getChannelId,track.getChannelId())
                .eq(CruiseTrack::getCruiseIndex,track.getCruiseIndex());
        CruiseTrack one = getOne(wrapper);
        return one;

    }

    /**
     * 添加或修改巡航轨迹
     *
     * @param dto
     * @return boolean
     * @author jgg
     * @date 2022/4/11 11:15
     */
    @Override
    public boolean addCruiseTrack(CruiseTrackDto dto) {
        CruiseTrack track = dto.build();
        CruiseTrack one = isSave(track);
        boolean flag;
        if(Objects.isNull(one)){
            flag = save(track);
        }else {
            track.setId(one.getId());
            flag = updateById(track);
        }
        visitPlat(track, INSERT);
        return flag;
    }



    /**
     * 删除巡航轨迹
     *
     * @param id
     * @return boolean
     * @author jgg
     * @date 2022/4/11 14:53
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteCruiseTrack(Integer id) {
        CruiseTrack track = getById(id);
        ResponseResult<CameraPlatform> result = cameraFeignInService.findById(track.getChannelId());
        CruiseDto dto = new CruiseDto(ResponseUtils.getCameraIndex(result), track.getCruiseIndex());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("OpType", DELETE);
        jsonObject.put("Data", JSON.toJSONString(dto));
        MqttOp.publish(MediaMqConstants.DISPLAY_CRUISE_TOPIC, JSON.toJSONString(jsonObject));
        return removeById(id);
    }

    /**
     * 启动/停止巡航
     *
     * @param control
     * @return boolean
     * @author jgg
     * @date 2022/4/11 16:08
     */
    @Override
    public boolean doCruise(CruiseControl control) {
        Integer cruiseId = control.getCruiseId();
        CruiseCommand command = control.getCommand();
        //查询轨迹信息
        CruiseTrack track = getById(cruiseId);
        //通过轨道信息查询对映的相机id
        Integer cruiseIndex = track.getCruiseIndex();
        if (Objects.equals(command, CRUISE_START)) {
            RedisUtil.set(PTZ_CRUISE + cruiseId, true);
        } else {
            RedisUtil.set(PTZ_CRUISE + cruiseId, false);
        }
        String hkCommand = command.getHkCommand();
        ResponseResult<CameraPlatform> result = cameraFeignInService.findById(track.getChannelId());
        CruiseDto dto = new CruiseDto(ResponseUtils.getCameraIndex(result), cruiseIndex, hkCommand);
        return cruisePathService.controlCruise(dto);
    }

    /**
     * 修改巡航轨迹
     *
     * @param dto
     * @return boolean
     * @author jgg
     * @date 2022/4/12 11:25
     */
    @Override
    public boolean updateCruiseTrack(CruiseTrackDto dto) {
        CruiseTrack track = dto.build();
        updateById(track);
        visitPlat(track, UPDATE);
        return true;
    }


    private void visitPlat(CruiseTrack track, String type) {
        ResponseResult result = cameraFeignInService.findById(track.getChannelId());
        CruiseDto dto =new CruiseDto(
                ResponseUtils.getCameraIndex(result),
                track.getCruiseIndex(),
                track.getCruiseName(),
                JSON.parseArray(track.getCruisePreset())
        );
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("OpType", type);
        jsonObject.put("Data", JSON.toJSONString(dto));
        MqttOp.publish(MediaMqConstants.DISPLAY_CRUISE_TOPIC, JSON.toJSONString(jsonObject));
    }

    /**
     * 通过通道id查询轨迹信息
     *
     * @param channelId
     * @return List<CruiseTrackDto>
     * @author jgg
     */
    @Override
    public List<CruiseTrackDto> selectListByChannelId(Integer channelId) {
        LambdaQueryWrapper<CruiseTrack> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(CruiseTrack::getChannelId,channelId)
                .orderByAsc(CruiseTrack::getCruiseIndex);
        List<CruiseTrackDto> dtoList = list(wrapper).stream().map(CruiseTrackDto::buildDto).collect(Collectors.toList());
        if(dtoList.size() < MAX_SIZE){
            List<Integer> indexList = dtoList.stream().map(CruiseTrackDto::getCruiseIndex).collect(Collectors.toList());
            for (int i = 1 ; i <= MAX_SIZE ; i++) {
                //判断当前索引是否有数据
                if (!indexList.contains(i)) {
                    //根据索引按顺序添加数据
                    dtoList.add(i - 1, new CruiseTrackDto(i, channelId));
                    continue;
                }
                CruiseTrackDto dto = dtoList.get(i - 1);
                Boolean convert = Convert.toBool(RedisUtil.get(PTZ_CRUISE + dto.getId()), false);
                dto.setCruising(convert);
            }
        }
        return dtoList;
    }
}
